﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace Ultrasonic
{
    public static class UltrasonicGlobal
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1)]//struTest变量在内存中的对齐方式

        //所有命令的命令头
        public struct UsbPrefix
        {
            public byte addr;
            public byte funcCode;
            public UInt16 length;				//total length include header(prefix)
        };

        public const int MAX_DATA_PACKAGE_SIZE = 128;



        public const byte ARTIFICIAL_BOARD_ADDR = 0x55;
        public const byte SCSX_MOTOR_TYPE= 1;
        public const byte SMX_MOTOR_TYPE = 0;
        #region 单个不带参数的命令。返回同样的数据以及CRC校验值，表示执行成功。
        public const byte CMD_BOARD_HANDSHAKE = 0x03;
        public const byte CMD_MILL_ON 		=	0x04;
        public const byte CMD_MILL_OFF      =   0x05;
        public const byte CMD_SET_WHEEL_SAME_SPEED = 0x12;
        #endregion

        #region 带参数的命令，参数为结构体的形式。
        public const byte CMD_SET_MOTOR_MEM_PARAMETER 		=	0x06;
        /// <summary>
        /// 单个设置电机内存表参数
        /// </summary>
        public struct SetMotorMemParameter
        {
            public byte motor_type;//scsx or smx
            public byte motor_id;
            public byte mem_addr;
            public byte param;
        };
        public const byte CMD_SET_WHEEL_SPEED 		=	0x07;
        //轮驱动电机不需要写位置，只需要控制速度，需要同步写。打磨压紧电机不需要速度只需要位置，且不需要同步写。
        public struct SetWheelSpeed
        {
            public byte motor_type;
            public byte wheel_id;
            public Int16 speed;
        }
        public const byte CMD_SET_MOTOR_POSITION = 0x08;
        public struct SetMotorPosition
        {
            public byte motor_type;
            public byte motor_id;
            public Int16 position;
            public UInt16 time;
            public Int16 speed;
        };
        /// <summary>
        /// 获取电机位置
        /// </summary>
        public const byte CMD_GET_MOTOR_POSITION = 0x09;
        public struct _GetMotorPosition
        {
	        public byte motor_type;
	        public byte motor_id;
            public Int32 position;
        };
        /// <summary>
        /// 获取当前速度
        /// </summary>
        public const byte CMD_GET_MOTOR_SPEED 	=		0x10;
        public struct _GetMotorSpeed
        {
	        public byte motor_type;
	        public byte motor_id;
            public Int16 speed;
        };
        /// <summary>
        /// 设置电机加速或者减速
        /// </summary>
        public const byte CMD_SET_MOTOR_ACCELERATE = 0x11;
        public struct _SetMotorAccelerate
        {
	        public byte motor_type;
	        public byte motor_id;
            public Int16 accelerate;
        };

        #endregion
        

        #region 将Byte转换为结构体类型StructToBytes(object structObj, int size)
        /// <summary>
        /// 将Byte转换为结构体类型
        /// </summary>
        /// <param name="structObj"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static byte[] StructToBytes(object structObj, int size)
        {
            byte[] bytes = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷贝到byte 数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }
        #endregion

        #region 合并两个byte[]数组，并返回合并后的数组
        /// <summary>
        /// 合并两个byte[]数组，并返回合并后的数组
        /// </summary>
        /// <param name="FirstByteArray"></param>
        /// <param name="SecondByteArray"></param>
        /// <returns></returns>
        public static byte[] MergeByte(byte[] FirstByteArray, byte[] SecondByteArray)
        {
            byte[] mergeByteArray = new byte[FirstByteArray.Length + SecondByteArray.Length];
            FirstByteArray.CopyTo(mergeByteArray, 0);
            SecondByteArray.CopyTo(mergeByteArray, FirstByteArray.Length);
            return mergeByteArray;
        }
        #endregion

        #region    将Byte转换为结构体类型函数ByteToStruct(byte[] bytes, Type type)
        /// <summary>
        /// 将Byte转换为结构体类型
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object ByteToStruct(byte[] bytes, Type type)
        {
            int size = Marshal.SizeOf(type);
            if (size > bytes.Length)
            {
                return null;
            }
            //分配结构体内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷贝到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return obj;
        }

        public static object ByteToStruct(byte[] bytes, int startAddr, Type type)
        {
            int size = Marshal.SizeOf(type);
            if (size > bytes.Length)
            {
                return null;
            }
            //分配结构体内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷贝到分配好的内存空间
            Marshal.Copy(bytes, startAddr, structPtr, size);
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return obj;
        }
        #endregion
    }
}
